<?php

namespace App\Services;

use App\Models\Category;
use App\Exceptions\BusinessException;
use Illuminate\Support\Str;

/**
 * 分类服务类
 * 
 * 职责：
 * - 处理分类相关的业务逻辑
 * - 分类创建、更新、删除的业务规则
 * - Slug生成和唯一性验证
 */
class CategoryService extends BaseService
{
    /**
     * 创建分类
     * 
     * @param array $data 分类数据
     * @return Category
     */
    public function create(array $data): Category
    {
        // 如果没有提供slug，从名称生成
        if (empty($data['slug'])) {
            $data['slug'] = $this->generateUniqueSlug($data['name']);
        } else {
            // 验证slug唯一性
            if (Category::where('slug', $data['slug'])->exists()) {
                $data['slug'] = $this->generateUniqueSlug($data['name']);
            }
        }

        return Category::create($data);
    }

    /**
     * 更新分类
     * 
     * @param Category $category 分类模型
     * @param array $data 更新数据
     * @return Category
     */
    public function update(Category $category, array $data): Category
    {
        // 处理slug
        if (isset($data['slug']) && $data['slug'] !== $category->slug) {
            if (Category::where('slug', $data['slug'])->where('id', '!=', $category->id)->exists()) {
                $data['slug'] = $this->generateUniqueSlug($data['name'] ?? $category->name);
            }
        } elseif (isset($data['name']) && $data['name'] !== $category->name) {
            // 名称改变时，如果没有提供新slug，自动生成
            if (!isset($data['slug'])) {
                $data['slug'] = $this->generateUniqueSlug($data['name']);
            }
        }

        $category->update($data);

        return $category->fresh();
    }

    /**
     * 删除分类
     * 
     * @param Category $category 分类模型
     * @return bool
     * @throws BusinessException
     */
    public function delete(Category $category): bool
    {
        // 检查分类下是否有文章
        if ($category->posts()->exists()) {
            $this->throwException('该分类下还有文章，无法删除', 400);
        }

        return $category->delete();
    }

    /**
     * 获取分类列表（带搜索）
     * 
     * @param array $filters 过滤条件
     * @param int $perPage 每页数量
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getList(array $filters = [], int $perPage = 15)
    {
        $query = Category::withCount('posts');

        // 搜索过滤
        if (!empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%");
            });
        }

        return $query->latest()->paginate($perPage)->withQueryString();
    }

    /**
     * 获取分类下的已发布文章
     * 
     * @param Category $category 分类模型
     * @param array $filters 过滤条件（如搜索）
     * @param int $perPage 每页数量
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getCategoryPosts(Category $category, array $filters = [], int $perPage = 9)
    {
        $query = \App\Models\Post::published()
            ->with(['author', 'category'])
            ->where('category_id', $category->id);

        // 搜索过滤
        if (!empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                  ->orWhere('content', 'like', "%{$search}%");
            });
        }

        return $query->latestPublished()
                     ->paginate($perPage)
                     ->withQueryString();
    }

    /**
     * 生成唯一的Slug
     * 
     * @param string $name 分类名称
     * @return string
     */
    protected function generateUniqueSlug(string $name): string
    {
        $slug = Str::slug($name);
        
        if (empty($slug)) {
            $slug = 'category-' . now()->format('YmdHis');
        }

        $baseSlug = $slug;
        $count = 1;

        while (Category::where('slug', $slug)->exists()) {
            $slug = $baseSlug . '-' . $count++;
        }

        return $slug;
    }

    /**
     * 获取分类统计（用于仪表盘）
     * 
     * @param int $limit 返回数量
     * @return \Illuminate\Support\Collection
     */
    public function getCategoryStats(int $limit = 5): \Illuminate\Support\Collection
    {
        return Category::withCount('posts')
            ->having('posts_count', '>', 0)
            ->orderByDesc('posts_count')
            ->limit($limit)
            ->get()
            ->map(fn ($category) => [
                'name' => $category->name,
                'count' => $category->posts_count
            ]);
    }
}

